package model.ds;

import java.util.ArrayList;

import model.HexDirection;
import model.PlayerColor;

import common.Tuple;

public interface GameBoardInterface {

	/**
	 * Moves a piece from one field to another. The target field has to be
	 * adjacent to an existing piece and the position is specified by the
	 * existing piece and a direction (leading to the neighbor).
	 * @param pieceIndex the index of the piece that is moved
	 * @param anchorPiece the piece that is adjacent to the target field
	 * @param direction the direction where the target field lies
	 * @return the number of the piece that already occupies the target field (if any). it is -1 if the field is empty
	 * @throws IllegalStateException if the game is already over
	 * @throws IllegalArgumentException if the target field is occupied and the moved piece does not support stacking
	 */
	public int move(int pieceIndex, int anchorPiece, HexDirection direction)
			throws IllegalStateException, IllegalArgumentException;

	/**
	 * Introduces the first piece to the board. This piece is from the white
	 * player.
	 * @param pieceType the type of the piece
	 * @throws IllegalStateException if another piece has already been set
	 * @throws IllegalArgumentException if the first piece is the queen
	 */
	public void introduce(PieceType pieceType) throws IllegalStateException,
			IllegalArgumentException;

	/**
	 * Introduces a new piece to the game board. The piece has to be placed
	 * adjacent to another piece.
	 * @param pieceType the type of the piece
	 * @param anchorPiece the piece specifying the adjacent field
	 * @param direction the direction of the target field (starting from the anchor field)
	 * @return the number of pieces introduced in total
	 */
	public int introduce(PieceType pieceType, int anchorPiece,
			HexDirection direction);

	/**
	 * Returns the piece type for a given piece identified by its index.
	 * @param i the index of the piece
	 * @return the type of the piece
	 */
	public PieceType getPieceType(int i);

	/**
	 * Returns the number of already introduced pieces.
	 * @return the number of already introduced pieces
	 */
	public int getIntroduced();

	/**
	 * Returns a list of fields that are reachable. They are defined as tuples of
	 * anchor fields and directions.
	 * @return a list of anchor fields and directions
	 */
	public ArrayList<Tuple<Integer, HexDirection>> getIntroduceable();

	/**
	 * Returns the number of pieces left for a specified player and a given type.
	 * @param player the player
	 * @param pieceType the piece type
	 * @return the number of pieces left for a specified player and a given type
	 */
	public int getLeftPiece(PlayerColor player, PieceType pieceType);

	/**
	 * Returns the current player.
	 * @return the current player
	 */
	public PlayerColor getCurrentPlayer();


	/**
	 * Decides if the game is over, or not.
	 * @return {@code true} if the game is over
	 */
	public boolean isGameOver();

	/**
	 * Decides whether the game ended draw. Can only be called when the game is over.
	 * @return {@code true} if the game is over and ended with a draw
	 * @throws IllegalStateException if the game is not ended yet
	 */
	public boolean isDraw() throws IllegalStateException;

	/**
	 * Returns the winner of the game, if it is ended already and is no draw.
	 * @return the winner of the game
	 * @throws IllegalStateException if the game has not finished yet or ended with a draw
	 */
	public PlayerColor getWinner() throws IllegalStateException;

}